package sanduche.controllers;

import java.util.List;

import models.Acudiente;
import models.CalendarioAcademico;
import models.Colegio;
import models.Curso;
import models.Estudiante;
import models.Grado;
import models.Materia;
import models.MateriaCurso;
import models.Matricula;
import models.Orientador;
import models.Periodo;
import models.Persona;
import models.Profesor;
import models.Secretario;
import play.db.jpa.Transactional;
import play.libs.Json;
import play.mvc.Http.Session;
import sanduche.play.shared.ModuleConfig;
import sanduche.play.shared.RequestBody;
import sanduche.play.shared.RequestMethod;
import sanduche.play.shared.Route;
import sanduche.play.shared.UrlParam;
import services.ColegioProcessSrv;
import services.ColegioSrv;
import services.DAO;
import util.SessionObj;

@ModuleConfig(prefix = "/api/coordinador")
public class CoordinadorController {

	private static SessionObj getSessionObj(Session session) {
		return Json.fromJson(
				Json.parse(session.get(UserController.SESSION_OBJ)),
				SessionObj.class);
	}

	private static long getIdCalendarioAcademicoActual(Session session) {
		return ColegioSrv.getColegio(
				getSessionObj(session).getCoordinador().getIdColegio())
				.getIdCalendarioAcademicoActual();
	}

	@Transactional
	@Route(value = "/go_next", method = RequestMethod.POST, iteratedClass = String.class)
	public static List<String> goNext(Session session)
			throws InstantiationException, IllegalAccessException {
		Colegio c = ColegioSrv.getColegio(getSessionObj(session)
				.getCoordinador().getIdColegio());
		List<String> s = ColegioProcessSrv.goNext(c);
		return s;
	}

	@Transactional
	@Route(value = "/estudiante", method = RequestMethod.GET, iteratedClass = Estudiante.class)
	public static List<Estudiante> getEstudiantes(Session session,
			@UrlParam("query") String query) {
		List<Estudiante> res = ColegioSrv.getEstudiantes(getSessionObj(session)
				.getCoordinador().getIdColegio(), query);
		return res;
	}

	@Transactional
	@Route(value = "/estudiante", method = RequestMethod.POST)
	public static Estudiante newEstudiante(Session session,
			@RequestBody Estudiante e) {

		Acudiente a = e.getAcudiente();
		if (a.getPersona().getId() != null) {
			DAO.merge(a.getPersona());
			a = DAO.execute(
					"SELECT a from Acudiente a WHERE a.persona.id = :idPersona",
					1, "idPersona", a.getPersona().getId());
		} else {
			ColegioSrv.crearActorConUsuario(a);
		}
		e.setIdAcudiente(a.getId());
		e.setIdColegio(getSessionObj(session).getCoordinador().getIdColegio());
		DAO.persist(e);
		DAO.flush();

		e.setAcudiente(a);
		// UserCreator.createUser(e);
		return e;
	}

	@Transactional(readOnly = true)
	@Route(value = "/grado", method = RequestMethod.GET, iteratedClass = Grado.class)
	public static List<Grado> getGrados(Session session) {

		return ColegioSrv.getGradosColegio(getSessionObj(session)
				.getCoordinador().getIdColegio());
	}

	@Transactional(readOnly = true)
	@Route(value = "/curso", method = RequestMethod.GET, iteratedClass = Curso.class)
	public static List<Curso> getCursosGrado(Session session,
			@UrlParam("idGrado") Long idGrado) {
		List<Curso> cursos = ColegioSrv.getCursosGrado(
				getIdCalendarioAcademicoActual(session), idGrado);
		return cursos;
	}

	@Transactional
	@Route(value = "/curso", method = RequestMethod.POST)
	public static Curso newCurso(Session session, @RequestBody Curso c) {

		c.setIdCalendarioAcademico(getIdCalendarioAcademicoActual(session));

		ColegioSrv.newCurso(c);

		return c;
	}

	@Transactional
	@Route(value = "/curso/:idCurso", method = RequestMethod.DELETE)
	public static void deleteCurso(Session session,
			@UrlParam("idCurso") Long idCurso) throws Exception {

		Curso c = DAO.find(Curso.class, idCurso);
		if (c.getIdCalendarioAcademico() == getIdCalendarioAcademicoActual(session)) {
			DAO.remove(c);
			DAO.flush();
			return;
		}

		throw new Exception(
				"El curso no se puede borrar. Probablemente tiene estudiantes inscritos");

	}

	@Transactional(readOnly = true)
	@Route(value = "/curso/:idCurso", method = RequestMethod.GET)
	public static Curso getCurso(@UrlParam("idCurso") Long idCurso) {
		return DAO.find(Curso.class, idCurso);
	}

	@Transactional(readOnly = true)
	@Route(value = "/materia_curso", method = RequestMethod.GET, iteratedClass = MateriaCurso.class)
	public static List<MateriaCurso> getMateriasCurso(
			@UrlParam("idCurso") Long idCurso) {

		return ColegioSrv.getMateriasCurso(idCurso);
	}

	@Transactional(readOnly = true)
	@Route(value = "/profesor", method = RequestMethod.GET, iteratedClass = Profesor.class)
	public static List<Profesor> getProfesores(Session session) {
		return DAO.query(Profesor.class, -1, "idColegio",
				getSessionObj(session).getCoordinador().getIdColegio());
	}

	@Transactional(readOnly = true)
	@Route(value = "/secretario", method = RequestMethod.GET, iteratedClass = Secretario.class)
	public static List<Secretario> getSecretarios(Session session) {
		return DAO.query(Secretario.class, -1, "idColegio",
				getSessionObj(session).getCoordinador().getIdColegio());
	}

	@Transactional
	@Route(value = "/profesor", method = RequestMethod.POST)
	public static Profesor newProfesor(Session session, @RequestBody Profesor c) {

		c.setIdColegio(getSessionObj(session).getCoordinador().getIdColegio());
		ColegioSrv.crearActorConUsuario(c);
		return c;
	}

	@Transactional
	@Route(value = "/secretario", method = RequestMethod.POST)
	public static Secretario newSecretario(Session session,
			@RequestBody Secretario c) {

		c.setIdColegio(getSessionObj(session).getCoordinador().getIdColegio());
		ColegioSrv.crearActorConUsuario(c);
		return c;
	}

	@Transactional
	@Route(value = "/orientador", method = RequestMethod.POST)
	public static Orientador newOrientador(Session session,
			@RequestBody Orientador c) {

		c.setIdColegio(getSessionObj(session).getCoordinador().getIdColegio());
		ColegioSrv.crearActorConUsuario(c);
		return c;
	}

	@Transactional
	@Route(value = "/materia_curso", method = RequestMethod.PUT)
	public static void updateMateriaCurso(@RequestBody MateriaCurso mc) {

		DAO.merge(mc);

	}

	@Transactional
	@Route(value = "/curso/:idCurso", method = RequestMethod.PUT)
	public static void updateCurso(@RequestBody Curso nc,
			@UrlParam("idCurso") Long idCurso) {
		DAO.merge(nc);

	}

	@Transactional
	@Route(value = "/matricula", method = RequestMethod.PUT)
	public static Matricula newMatricula(Session session,
			@RequestBody Matricula m) {

		m.setIdCalendarioAcademico(getIdCalendarioAcademicoActual(session));
		DAO.merge(m);
		return m;
	}

	@Transactional
	@Route(value = "/estudiante/:idEstudiante", method = RequestMethod.PUT)
	public static void updateEstudiante(@RequestBody Estudiante e,
			@UrlParam("idEstudiante") Long idEstudiante) {

		e.setId(idEstudiante);
		DAO.merge(e);
		if (e.getAcudiente() != null)
			DAO.merge(e.getAcudiente());

	}

	@Transactional
	@Route(value = "/persona/:idPersona", method = RequestMethod.PUT)
	public static void updatePersona(@RequestBody Persona p,
			@UrlParam("idPersona") Long idPersona) {

		p.setId(idPersona);
		DAO.merge(p);

	}

	@Transactional(readOnly = true)
	@Route(value = "/materia", method = RequestMethod.GET, iteratedClass = Materia.class)
	public static List<Materia> getMaterias(Session session) {
		// FIXME agregar el metodo materias grado
		return ColegioSrv.getMateriasColegio(getSessionObj(session)
				.getCoordinador().getIdColegio());
	}

	@Transactional(readOnly = true)
	@Route(value = "/calendario_academico", method = RequestMethod.GET)
	public static CalendarioAcademico getCalendarioAcademicoActual(
			Session session) {
		Colegio c = ColegioSrv.getColegio(getSessionObj(session)
				.getCoordinador().getIdColegio());
		CalendarioAcademico p = DAO.find(CalendarioAcademico.class,
				c.getIdCalendarioAcademicoActual());
		return p;
	}

	@Transactional
	@Route(value = "/calendario_academico", method = RequestMethod.PUT)
	public static void updateCalendarioAcademico(Session session,
			@RequestBody CalendarioAcademico p,
			@UrlParam("idCalendarioAcademico") Long idCalendarioAcademico) {

		p.setIdColegio(getSessionObj(session).getCoordinador().getIdColegio());
		int i = 1;
		for (Periodo c : p.getPeriodos()) {
			c.setCalendarioAcademico(p);
			c.setNumero(i++);
		}

		DAO.merge(p);

	}

	@Transactional
	@Route(value = "/estudiante", method = RequestMethod.GET, iteratedClass = Estudiante.class)
	public static List<Estudiante> getEstudiantesCurso(Session session,
			@UrlParam("idCurso") Long idCurso) {

		List<Estudiante> estudiantes = DAO
				.execute(
						"SELECT e FROM Estudiante e, Matricula m WHERE e.id = m.idEstudiante AND m.idCurso = :idCurso AND m.idCalendarioAcademico = :idCalendarioAcademico",
						-1, "idCurso", idCurso, "idCalendarioAcademico",
						getIdCalendarioAcademicoActual(session));
		System.out.println(estudiantes);
		return estudiantes;
	}

}
